package com.sinosoft.web.easyui.api;

import com.sinosoft.hydra.logging.LogModules;
import cn.com.sinux.spring.commons.PropertyCollection;
import com.sinosoft.hydra.um.condition.SearchLogCondition;
import com.sinosoft.hydra.um.domain.permission.SysLogInfo;
import com.sinosoft.hydra.um.domain.permission.SysLogPackage;
import com.sinosoft.hydra.um.helper.LoggerHelper;
import com.sinosoft.hydra.um.services.SysLogInfoService;
import cn.com.sinux.spring.utils.DateUtils;
import com.sinosoft.hydra.um.domain.model.LogInfo4Chart;
import cn.com.sinux.spring.utils.PageUtils;
import com.sinosoft.hydra.um.vo.LogVo;
import cn.com.sinux.spring.json.JsonFilter;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.util.*;

/**
 * 日志访问API 实现日志管理中日志列表和日志报表的功能
 *
 * @author zhengt
 * @author chendl
 * @version 0.5-alpha
 */
@Controller
@RequestMapping("api/sysLog")
public class SysLogApi {

    /**
     * 日志的service层SysLogInfoService实现功能
     */
    @Autowired
    private SysLogInfoService sysLogInfoService;

    /**
     * 初始化进入页面
     *
     * @return 返回页面
     */
    @RequestMapping(value = "/queryLog")
    @RequiresPermissions(value = "log:data:list")
    public String index() {
//        LoggerHelper.logInfo("查询了日志列表信息");
        return "hydra_easyui/log/index";
    }

    /**
     * 获取查询的json
     *
     * @param pageNumber         分页查询的页数
     * @param pageSize           分页查询每页显示条数
     * @param searchLogCondition 日志对象
     * @return 返回查询的所有数据JSON格式
     */
    @RequestMapping(value = "/query")
    @ResponseBody
    //修改返回类型为json格式的字符串
    public Object queryLog(
            @RequestParam(value = "page", required = false, defaultValue = "1") Integer pageNumber,
            @RequestParam(value = "rows", required = false, defaultValue = "10") Integer pageSize,
            SearchLogCondition searchLogCondition) {
        if (searchLogCondition.getEndDate() == null) {
            searchLogCondition.setEndDate(new Date());
        }
        Page<SysLogInfo> page = sysLogInfoService.findAllByPage(PageUtils
                .buildPageRequest(pageNumber, pageSize, "createDate", "desc"), searchLogCondition);
        return page;
    }

    /**
     * 日志删除操作
     *
     * @param searchLogCondition 需要删除的id的列表，格式JsonList(eg:{"ids":["1","2","3"]}) 可为空
     * @return 返回操作结果
     */
    @RequestMapping(value = "/logDelete", method = RequestMethod.POST)
    @ResponseBody
    @RequiresPermissions(value = "log:data:delete")
    public Object delete(SearchLogCondition searchLogCondition) {
        List<SysLogInfo> logInfos = sysLogInfoService.delete(searchLogCondition.getIds());
        LoggerHelper.logInfo("删除了日志信息以下时间点的日志{}", new LoggerHelper.PropertyReader<SysLogInfo>(logInfos, "createDate"));
        return JsonFilter.doPropertyFilter(logInfos, new PropertyCollection()
                .addProperties(SysLogInfo.class, "id"));
    }

    /**
     * 详细信息显示
     *
     * @param id    查询的日志id
     * @param model 将返回页面信息放入model
     * @return 返回详细信息显示页面数据放入到model中
     */
    @RequestMapping(value = "/findOne")
    @RequiresPermissions(value = "log:data:list")
    public String findOne(@RequestParam(value = "id", required = true) String id, Model model) {
        LogVo lv = sysLogInfoService.findOne(id);
        model.addAttribute("lv", lv);
        return "hydra_easyui/log/queryLogInfo";
    }

    /**
     * 日志列表 打包操作
     *
     * @param searchLogCondition ids
     * @return 返回操作情况，如：打包成功，打包失败
     * @throws java.io.IOException 文件读写异常
     */
    @RequestMapping(value = "/pack")
    @ResponseBody
    @RequiresPermissions(value = "log:data:package")
    public Object packages(SearchLogCondition searchLogCondition)
            throws IOException {
        LoggerFactory.getLogger(LogModules.TRACE_LOGGER).info("进行了日志的打包操作：{}", searchLogCondition.getIds());
        List<SysLogPackage> logPackages = sysLogInfoService.packages(searchLogCondition.getIds(), searchLogCondition.isAll());
        LoggerHelper.logInfo("对日志进行了打包，生成打包记录{}", new LoggerHelper.PropertyReader<SysLogPackage>(logPackages, "packageName"));
        return JsonFilter.doPropertyFilter(logPackages, new PropertyCollection()
                .addProperties(SysLogPackage.class, "id"));
    }

    /**
     * 点击搜索后的跳转页面
     *
     * @param model 将返回页面信息放入model
     * @return 返回日志搜索页面
     */
    @RequestMapping(value = "/searchLog")
    @RequiresPermissions(value = "log:data:list")
    public String searchLog(Model model) {
        return "hydra_easyui/log/search";
    }

    /**
     * 日志报表的跳转
     *
     * @return 返回日志报表页面
     */
    @RequestMapping("toReport")
    @RequiresPermissions(value = "log:data:report")
    public String toReport(Model model) {
        Date now = new Date();
        model.addAttribute("begin", DateFormatUtils.format(DateUtils.addWeeks(now, -1), "yyyy-MM-dd"));
        model.addAttribute("end", DateFormatUtils.format(now, "yyyy-MM-dd"));
        LoggerFactory.getLogger(LogModules.TRACE_LOGGER).info("查看了日志的报表信息");
        return "hydra_easyui/logReport/logReport";
    }

    /**
     * 调用报表饼状图
     *
     * @param searchLogCondition 开始日期
     * @param model              将返回页面信息放入model
     * @return 报表内容
     */
    @ResponseBody
    @RequestMapping("report4Pie")
    public Object report4Pie(SearchLogCondition searchLogCondition, Model model) {
        if (searchLogCondition.getBeginDate() == null) {
            searchLogCondition.setBeginDate(new Date());
        }
        if (searchLogCondition.getEndDate() == null) {
            searchLogCondition.setEndDate(new Date());
        }
        searchLogCondition.setBeginDate(DateUtils.getStartOfDay(searchLogCondition.getBeginDate()));
        searchLogCondition.setEndDate(DateUtils.getEndOfDay(searchLogCondition.getEndDate()));
        final Map<String, Object> map = sysLogInfoService.queryCountForReport(
                searchLogCondition.getBeginDate(), searchLogCondition.getEndDate());
        // order for pie[INFO>TRACE>DEBUG>WARN>ERROR]
        Boolean hasrows = false;
        final List<String> pieOrders = reportParts;
        List<LogInfo4Chart> list = new ArrayList<LogInfo4Chart>() {
            {
                for (String str : pieOrders) {
                    LogInfo4Chart lc = new LogInfo4Chart();
                    lc.setValue(map.containsKey(str) ? String.valueOf(map.get(str))
                            : "0");
                    lc.setName(str);
                    add(lc);
                }
            }
        };
        // 如果都没有数据那么记录一个标识
        for (LogInfo4Chart logInfo4Chart : list) {
            if (!logInfo4Chart.getValue().equals("0")) {
                hasrows = true;
            }
        }
        Map<String, Object> retMap = new HashMap<String, Object>();
        if (!hasrows) {
            list = new ArrayList<LogInfo4Chart>();
            LogInfo4Chart lc = new LogInfo4Chart();
            lc.setValue("1");
            lc.setName("最近一周没有记录任何日志!");
            list.add(lc);
            retMap.put("legend", "");
            retMap.put("series", list);
        } else {
            retMap.put("legend", pieOrders);
            retMap.put("series", list);
        }
        return retMap;
    }

    /**
     * 报表的折线图
     *
     * @param searchLogCondition 开始日期
     * @param searchType         搜索的类型
     * @param model              将返回页面信息放入model
     * @return 返回查询到的内容
     */
    @ResponseBody
    @RequestMapping("report4Line")
    public Object report4Line(
            SearchLogCondition searchLogCondition,
            @RequestParam(required = false, defaultValue = "ymd") String searchType,
            Model model) {
//		final Map<String, String> map = sysLogInfoService.queryCountForReport(startDate, endDate);
        // order for line[INFO>TRACE>DEBUG>WARN>ERROR]
        Map<String, Object> retMap = new HashMap<String, Object>();
        if (searchLogCondition.getBeginDate() == null) {
            searchLogCondition.setBeginDate(new Date());
        }
        if (searchLogCondition.getEndDate() == null) {
            searchLogCondition.setEndDate(new Date());
        }
        searchLogCondition.setBeginDate(DateUtils.getStartOfDay(searchLogCondition.getBeginDate()));
        searchLogCondition.setEndDate(DateUtils.getStartOfDay(searchLogCondition.getEndDate()));
        if (searchType.equals("y")) {
            retMap.putAll(sysLogInfoService.queryLogInfoListByYear(searchLogCondition.getBeginDate(), searchLogCondition.getEndDate()));
        } else if (searchType.equals("ym")) {
            retMap.putAll(sysLogInfoService.queryLogInfoListByYearMonth(searchLogCondition.getBeginDate(), searchLogCondition.getEndDate()));
        } else if (searchType.equals("ymd")) {
            retMap.putAll(sysLogInfoService.queryLogInfoList(searchLogCondition.getBeginDate(), searchLogCondition.getEndDate()));
        }
        retMap.put("legend", reportParts);
        return retMap;
    }

    /**
     * <p>组装报表显示的块
     *
     * @return List<String> 页面显示的内容分类
     */
    private static List<String> reportParts = Arrays.asList("INFO", "TRACE", "DEBUG", "WARN", "ERROR");
}
